﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using SchemaExplorer;
using Tilver.Coder.CommandExcuteResult;
using Tilver.Coder.Core;
using System.Reflection;

namespace Tilver.Coder.Utility
{
    public static class ExtensionUtil
    {
        #region 扩展SchemaExplorer

        /// <summary>
        /// 转换为存储过程
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public static CoderCommand ToCoderCommand(this CommandSchema command)
        {
            var result = new CoderCommand();
            result.Name = command.Name;
            result.Owner = command.Owner;
            result.FullName = command.FullName;
            result.CodeName = command.Name.ToCoderCodeName();
            result.EOName = result.CodeName.ToCoderEOClassName();
            //result.DataBase = dataBase;
            result.MOInfo = new CoderMOInfo();
            result.State = ObjectStateEnum.New;
            result.IsBuild = false;
            result.Description = command.Description;
            
            result.CommandText = command.CommandText;

            #region 加载参数
            if (command.Parameters != null && command.Parameters.Count > 0)
            {
                foreach (var parameter in command.Parameters)
                {
                    result.Parameters.Add(parameter.ToCoderParameter());
                }
            }
            #endregion
            result.CommandResult = ExecuteResultUtil.Create(ExecuteResultEnum.ExecuteNonQuery);
            return result;
        }
        /// <summary>
        /// 转换为视图
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        public static CoderView ToCoderView(this ViewSchema view)
        {
            var result = new CoderView();
            result.Name = view.Name;
            result.Owner = view.Owner;
            result.FullName = view.FullName;
            result.CodeName = view.Name.ToCoderCodeName();
            result.EOName = result.CodeName.ToCoderEOClassName();
            //result.DataBase = dataBase;
            result.MOInfo = new CoderMOInfo();
            result.State = ObjectStateEnum.New;
            result.IsBuild = false;
            result.Description = view.Description;
            #region 加载列
            //result.Columns = view.Columns.Select(s => s.ToCoderColumn()).ToList();
            if (view.Columns != null && view.Columns.Count > 0)
            {
                foreach (var column in view.Columns)
                {
                    result.Columns.Add(column.ToCoderColumn());
                }
            }
            #endregion

            return result;
        }
        /// <summary>
        /// 转换为表
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public static CoderTable ToCoderTable(this TableSchema table)
        {
            var result = new CoderTable();
            result.Name = table.Name;
            result.Owner = table.Owner;
            result.FullName = table.FullName;
            result.CodeName = table.Name.ToCoderCodeName();
            result.EOName = result.CodeName.ToCoderEOClassName();
            //result.DataBase = dataBase;
            result.MOInfo = new CoderMOInfo();
            result.State = ObjectStateEnum.New;
            result.IsBuild = false;
            result.Description = table.Description;

            //处理字段
            //result.Columns = table.Columns.Select(s => s.ToCoderColumn()).ToList();
            //result.ForeignKeys = table.ForeignKeys.Select(s => s.ToCoderTableKey()).ToList();
            #region 加载列
            //result.Columns = view.Columns.Select(s => s.ToCoderColumn()).ToList();
            if (table.Columns != null && table.Columns.Count > 0)
            {
                foreach (var cColumn in table.Columns.Select(appendColumn => appendColumn.ToCoderColumn()))
                {
                    cColumn.Table = result;
                    //处理枚举类型
                    if (CoderEnum.IsEnumType(cColumn))
                    {
                        cColumn.IsEnumType = true;
                        cColumn.AllowGenerateEnum = true;
                        //CustomerInfoEO.TypeEnum
                        cColumn.CSharpType = string.Format("{0}.{1}{2}",
                            result.EOName,
                            cColumn.CodeName.ToCoderEnumName(),
                            cColumn.AllowDBNull ? "?" : string.Empty);
                    }
                    result.Columns.Add(cColumn);
                }
            }
            #endregion

            #region  加载索引
            if (table.Indexes != null && table.Indexes.Count > 0)
            {
                foreach (var index in table.Indexes.Select(appendIndex => appendIndex.ToCoderIndex()))
                {
                    index.Table = result;
                    result.Indexes.Add(index);
                }
            }
            #endregion

            #region 加载主健
            if (table.HasPrimaryKey)
            {
                var pk = table.PrimaryKey.ToCoderPrimaryKey();
                pk.Table = result;
                result.PrimaryKey = pk;
            }
            #endregion

            #region 加载外健
            if (table.ForeignKeys != null && table.ForeignKeys.Count > 0)
            {
                foreach (var key in table.ForeignKeys.Select(foreignKey => foreignKey.ToCoderTableKey()))
                {
                    
                    result.ForeignKeys.Add(key);
                }
            }

            #endregion
            return result;
        }
        /// <summary>
        /// 转换列
        /// </summary>
        /// <param name="csColumn"></param>
        /// <returns></returns>
        public static CoderColumn ToCoderColumn(this ColumnSchema csColumn)
        {
            var result = new CoderColumn();
            csColumn.ToCoderDataObject(result);
            //result.Table = table;
            result.IsPrimaryKey = csColumn.IsPrimaryKeyMember;
            result.IsForeignKey = csColumn.IsForeignKeyMember;
            result.IsUnique = csColumn.IsUnique;
            result.IsIdentity = csColumn.IsIdentity();
            return result;
        }
        /// <summary>
        /// 转换列
        /// </summary>
        /// <param name="csColumn"></param>
        /// <returns></returns>
        public static CoderColumn ToCoderColumn(this ViewColumnSchema csColumn)
        {
            var result = new CoderColumn();
            csColumn.ToCoderDataObject(result);
            result.IsPrimaryKey = false;
            result.IsForeignKey = false;
            result.IsUnique = false;
            result.IsIdentity = false;
            return result;
        }
        /// <summary>
        /// 转换参数
        /// </summary>
        /// <param name="csParameter"></param>
        /// <returns></returns>
        public static CoderParameter ToCoderParameter(this ParameterSchema csParameter)
        {
            var result = new CoderParameter();
            //csParameter.Database.GetDataProviderType();
            csParameter.ToCoderDataObject(result);
            result.CodeName = csParameter.Database.ToCoderDBTextStyle().Clean(csParameter.Name).ToCoderCodeName();
            result.Direction = csParameter.Direction;
            result.Value = string.Empty;
            return result;
        }
        /// <summary>
        /// 转换成数据对象
        /// </summary>
        /// <param name="csDataObject"></param>
        /// <param name="dataObject"></param>
        public static void ToCoderDataObject(this DataObjectBase csDataObject, CoderDataObject dataObject)
        {
            dataObject.Name = csDataObject.Name;
            dataObject.CodeName = csDataObject.Name.ToCoderCodeName();
            dataObject.DbType = csDataObject.DataType;
            dataObject.NativeType = csDataObject.NativeType;
            dataObject.AllowDBNull = csDataObject.AllowDBNull;
            dataObject.Precision = csDataObject.Precision;
            dataObject.Scale = csDataObject.Scale;
            dataObject.Size = csDataObject.Size;
            dataObject.DefaultValue = csDataObject.GetColumnDefaultValue();
            dataObject.Description = csDataObject.Description;
            dataObject.IsEnumType = false;
            dataObject.AllowGenerateEnum = false;
            dataObject.CSharpType = DBTypeUtil.ConvertToCSharpType(dataObject.DbType, dataObject.AllowDBNull);
            dataObject.State = ObjectStateEnum.Normal;
        }
        /// <summary>
        /// 转换成索引
        /// </summary>
        /// <param name="csIndex"></param>
        /// <returns></returns>
        public static CoderIndex ToCoderIndex(this IndexSchema csIndex)
        {
            var result = new CoderIndex();
            //result.Table = table;
            result.Name = csIndex.Name;
            result.IsClustered = csIndex.IsClustered;
            result.IsPrimaryKey = csIndex.IsPrimaryKey;
            result.IsUnique = csIndex.IsUnique;
            result.Description = csIndex.Description;
            result.MemberColumnNames = csIndex.MemberColumns.Select(w => w.Name).ToList();
            return result;
        }
        /// <summary>
        /// 转换成表的健值
        /// </summary>
        /// <param name="csTableKey"></param>
        /// <returns></returns>
        public static CoderTableKey ToCoderTableKey(this TableKeySchema csTableKey)
        {
            var result = new CoderTableKey();
            result.Name = csTableKey.Name;
            //result.DataBase = dataBase;
            result.PrimayTableFullName = csTableKey.PrimaryKeyTable.FullName;
            result.PrimaryColumnNames = csTableKey.PrimaryKeyMemberColumns.Select(w => w.Name).ToList();
            result.ForeignTableFullName = csTableKey.ForeignKeyTable.FullName;
            result.ForeignColumnNames = csTableKey.ForeignKeyMemberColumns.Select(w => w.Name).ToList();
            result.Description = csTableKey.Description;
            return result;

        }
        /// <summary>
        /// 转换成表的主健
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <returns></returns>
        public static CoderPrimaryKey ToCoderPrimaryKey(this PrimaryKeySchema primaryKey)
        {
            var result = new CoderPrimaryKey();
            result.Name = primaryKey.Name;
            //result.Table = table;
            result.MemberColumnNames = primaryKey.MemberColumns.Select(w => w.Name).ToList();
            result.Description = primaryKey.Description;
            return result;
        }
        /// <summary>
        /// 查询表
        /// </summary>
        /// <param name="dataBase"></param>
        /// <param name="tableFullName"></param>
        /// <returns></returns>
        public static CoderTable FindTable(this CoderDataBase dataBase, string tableFullName)
        {
            return dataBase.Tables.FirstOrDefault(c => c.FullName == tableFullName);
        }
        /// <summary>
        /// 搜索列
        /// </summary>
        /// <param name="table"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static CoderColumn FindColumn(this CoderTable table, string columnName)
        {
            return table.Columns.FirstOrDefault(c => c.Name == columnName);
        }
        /// <summary>
        /// 搜索一组列
        /// </summary>
        /// <param name="table"></param>
        /// <param name="columnNames"></param>
        /// <returns></returns>
        public static IEnumerable<CoderColumn> FindColumns(this CoderTable table, IList<string> columnNames)
        {
            return table.Columns.Where(c => columnNames.Contains(c.Name));
        }
        /// <summary>
        /// 获取数据库本文式样
        /// </summary>
        /// <param name="db"></param>
        /// <returns></returns>
        public static DBTextStyle.DBTextStyleBase ToCoderDBTextStyle(this DatabaseSchema db)
        {
            return DBTextStyleUtil.GetDBTextStyle(db.GetDataProviderType());
        }
        /// <summary>
        /// 获得数据提供程序名对应的提供程序类型
        /// </summary>
        /// <returns></returns>
        public static DataProviderTypeEnum GetDataProviderType(this DatabaseSchema csDatabase)
        {
            DataProviderTypeEnum ret;
            switch (csDatabase.Provider.Name)
            {
                case "OracleSchemaProvider":
                    ret = DataProviderTypeEnum.Oracle;
                    break;
                case "SqlSchemaProvider":
                    ret = DataProviderTypeEnum.MSSQL;
                    break;
                default:
                    ret = DataProviderTypeEnum.MSSQL;
                    break;
            }
            return ret;
        }
        /// <summary>
        /// 是否唯一
        /// </summary>
        /// <param name="csDataObject"></param>
        /// <returns></returns>
        public static bool IsIdentity(this DataObjectBase csDataObject)
        {
            return csDataObject.ExtendedProperties.Contains("CS_IsIdentity") ? csDataObject.ExtendedProperties["CS_IsIdentity"].Value.ToString().ToLower() == "true" : false;
        }
        /// <summary>
        /// 获取列的默认值
        /// </summary>
        /// <param name="csDataObject"></param>
        /// <returns></returns>
        public static string GetColumnDefaultValue(this DataObjectBase csDataObject)
        {
            return csDataObject.ExtendedProperties.Contains("CS_Default") ? csDataObject.ExtendedProperties["CS_Default"].Value.ToString() : string.Empty;
        }
        #endregion

        #region 扩展StringBuilder
        /// <summary>
        /// 产生n个Tab输入
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static string Tab(int n)
        {
            const char tab = '\t';
            return new string(tab, n);
        }
        /// <summary>
        /// 添加n个TAB
        /// </summary>
        /// <param name="sb">输出流</param>
        /// <param name="n">tab的数量</param>
        public static void AppendTab(this StringBuilder sb, int n)
        {
            sb.Append(Tab(n));
        }

        /// <summary>
        /// 添加n个tab  + value 
        /// </summary>
        /// <param name="sb">输出流</param>
        /// <param name="n">tab的数量</param>
        /// <param name="value">将要添加的字符串</param>
        public static void AppendTab(this StringBuilder sb, int n, string value)
        {
            sb.Append(Tab(n) + value);
        }

        /// <summary>
        /// 添加n个tab后 ，换行
        /// </summary>
        /// <param name="sb">输出流</param>
        /// <param name="n">tab的数量</param>
        public static void AppendTabLine(this StringBuilder sb, int n)
        {
            sb.AppendLine(Tab(n));
        }

        /// <summary>
        /// 添加n个tab  + value 后 ,换行
        /// </summary>
        /// <param name="sb">输出流</param>
        /// <param name="n">tab的数量</param>
        /// <param name="value">将要添加的字符串</param>
        public static void AppendTabLine(this StringBuilder sb, int n, string value)
        {
            sb.AppendLine(Tab(n) + value);
        }

        /// <summary>
        /// 添加n个tab + 格式化
        /// </summary>
        /// <param name="sb">输出流</param>
        /// <param name="tabs">tab的数量</param>
        /// <param name="format">格式化</param>
        /// <param name="args">格式化参数</param>
        public static void AppendFormat(this StringBuilder sb, int tabs, string format, params object[] args)
        {
            sb.AppendTab(tabs);
            sb.AppendFormat(format, args);
        }

        /// <summary>
        /// 格式化后换行
        /// </summary>
        /// <param name="sb">输出流</param>
        /// <param name="tabs">Tab个数</param>
        /// <param name="format">格式化</param>
        /// <param name="args">格式化参数</param>
        public static void AppendFormatLine(this StringBuilder sb, int tabs, string format, params object[] args)
        {
            sb.AppendFormat(tabs, format, args);
            sb.AppendLine();
        }
        #region 生成注释
        /// <summary>
        /// 获得自定义Summary注释
        /// </summary>
        /// <param name="tabs">tab的数量</param>
        /// <param name="desc">描述</param>       
        /// <returns></returns>
        public static string GetCoderSummary(int tabs, string desc)
        {
            return GetCoderSummary(tabs, desc, delegate(string firstLine) { return firstLine; });
        }

        /// <summary>
        /// 获得自定义Summary注释
        /// </summary>
        /// <param name="tabs">tab的数量</param>
        /// <param name="desc">描述</param> 
        /// <param name="subDesc">描述补充 ，放在描述末尾</param>
        /// <returns></returns>
        public static string GetCoderSummary(int tabs, string desc, string subDesc)
        {
            return GetCoderSummary(tabs, desc, delegate(string firstLine) { return string.Format("{0} 《{1}》", firstLine, subDesc); });
        }

        /// <summary>
        /// 获得自定义Summary注释
        /// </summary>        
        /// <param name="tabs">tab的数量</param>
        /// <param name="desc">描述</param> 
        /// <param name="formatFirstLineFunction">格式化首行注释的方法，参数为首行注释，返回值为格式化后的注释</param>
        /// <returns></returns>
        public static string GetCoderSummary(int tabs, string desc, Func<string, string> formatFirstLineFunction)
        {
            var sb = new StringBuilder();
            var descs = desc.ToCoderArrayByNewLine();
            sb.Append(Tab(tabs));
            sb.AppendLine("/// <summary>");
            sb.Append(Tab(tabs));
            sb.AppendLine(string.Format("/// {0}", formatFirstLineFunction(descs.Length == 0 ? string.Empty : descs[0])));
            sb.Append(Tab(tabs));
            sb.Append("/// </summary>");

            if (descs.Length > 1)
            {
                sb.AppendLine();
                sb.Append(Tab(tabs));
                sb.AppendLine("/// <remarks>");
                for (var i = 1; i < descs.Length; i++)
                {
                    sb.Append(Tab(tabs));
                    sb.AppendLine("/// " + descs[i]);
                }
                sb.Append(Tab(tabs));
                sb.Append("/// </remarks>");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 获取一个参数的注释
        /// </summary>
        /// <param name="tabs">tab的数量</param>
        /// <param name="name">参数名称</param>
        /// <param name="desc">参数注释</param>
        /// <returns></returns>
        public static string GetCoderParamSummary(int tabs, string name, string desc)
        {
            return GetCoderSummary(tabs, "param", string.Format("name = \"{0}\"", name), desc);
        }
        /// <summary>
        /// 生成参数注释代码
        /// </summary>
        /// <param name="tabs">输入Tab数</param>
        /// <param name="type"></param>
        /// <param name="attributes"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        private static string GetCoderSummary(int tabs, string type, string attributes, string desc)
        {
            var sb = new StringBuilder();
            string[] descs = desc.ToCoderArrayByNewLine();
            string startTag = string.Format("<{0}{1}{2}>", type, string.IsNullOrEmpty(attributes) ? string.Empty : " ", attributes);
            string endTag = string.Format("</{0}>", type);
            if (descs.Length <= 1)
            {
                sb.AppendFormat("{0}/// {1}{2}{3}", Tab(tabs), startTag, descs.Length == 0 ? string.Empty : descs[0], endTag);
            }
            else
            {
                sb.AppendLine(string.Format("{0}/// {1}", Tab(tabs), startTag));
                for (int i = 0; i < descs.Length; i++)
                {
                    sb.AppendFormatLine(tabs, "/// {0}", descs[i]);
                }
                sb.AppendFormat(tabs, "/// {0}", endTag);
            }
            return sb.ToString();
        }
        /// <summary>
        /// 获得事务管理对象的注释
        /// </summary>
        /// <param name="tabs">tab的数量</param>
        /// <returns></returns>
        public static string GetCoderTMSummary(int tabs)
        {
            return Tab(tabs) + "/// <param name=\"tm\">事务管理对象</param>";
        }

        /// <summary>
        /// 返回结果注释
        /// </summary>
        /// <param name="tabs">tab的数量</param>
        /// <param name="desc">注释</param>
        /// <returns></returns>
        public static string GetCoderReturnSummary(int tabs, string desc)
        {
            return GetCoderSummary(tabs, "return", null, desc);
        }
        #endregion

        #endregion

        #region 扩展String
        /// <summary>
        /// 如果生成的名称为保留字则添加的后缀
        /// </summary>
        public const string APPEND_CSHARP_RESERVED = "Value";

        /// <summary>
        /// C#保留字
        /// </summary>
        public static Regex CSharpReserved = new Regex("^(ABSTRACT|AS|BASE|BOOL|BREAK|BYTE|CASE|CATCH|CHAR|CHECKED|CLASS|CONST|CONTINUE|DECIMAL|DEFAULT|DELEGATE|DO|DOUBLE|ELSE|ENUM|EVENT|EXPLICIT|EXTERN|FALSE|FINALLY|FIXED|FLOAT|FOR|FOREACH|GET|GOTO|IF|IMPLICIT|IN|INT|INTERFACE|INTERNAL|IS|LOCK|LONG|NAMESPACE|NEW|NULL|OBJECT|OPERATOR|OUT|OVERRIDE|PARAMS|PARTIAL|PRIVATE|PROTECTED|PUBLIC|READONLY|REF|RETURN|SBYTE|SEALED|SET|SHORT|SIZEOF|STACKALLOC|STATIC|STRING|STRUCT|SWITCH|THIS|THROW|TRUE|TRY|TYPEOF|UINT|ULONG|UNCHECKED|UNSAFE|USHORT|USING|VALUE|VIRTUAL|VOID|VOLATILE|WHERE|WHILE|YIELD)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        /// <summary>
        /// 非法字符
        /// </summary>
        private static char[] _cleanChars = new char[] { ' ', '_', '-', '.' };
        /// <summary>
        /// 清除非法字符,并且非法字符之后的第一个字符为大写
        /// </summary>
        /// <param name="value">字符串</param>
        /// <returns>字符串</returns>
        private static string CleanWords(this string value)
        {
            string ret = string.Empty;
            string[] items = value.Split(_cleanChars, StringSplitOptions.RemoveEmptyEntries);
            foreach (string str in items)
            {
                ret += (char.ToUpper(str[0]) + str.Substring(1)).Trim();
            }
            return ret;
        }

        /// <summary>
        /// 转换关键字，如果为关键字，则在字符串末尾添加字符‘Value'
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string ConvertToKeyWord(this string value)
        {
            if (CSharpReserved.IsMatch(value))
            {
                value += APPEND_CSHARP_RESERVED;
            }

            return value;
        }

        /// <summary>
        /// 转化为合法的变量名(首字母必须是以[a-zA-Z]开头)；如果不是合法的变量名，开头加关键字'Coder'
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string ConvertToLegalName(this string value)
        {
            if ((value[0] >= 'a' && value[0] <= 'z') ||
                (value[0] >= 'A' && value[0] <= 'Z'))
                return value;
            return "Coder" + value;
        }
        /// <summary>
        /// 将一个名称转换为程序内部使用的名称(合法的变量名称)
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderCodeName(this string name)
        {
            return name.CleanWords().ConvertToKeyWord().ConvertToLegalName();
        }

        /// <summary>
        /// 使用camel命名法，首字母小写
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToCoderCamelCase(this string value)
        {
            return char.ToLower(value[0]) + value.Substring(1);
        }

        /// <summary>
        /// 使用Pascal命名法，首字母大写
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToCoderPascalCase(this string value)
        {
            return char.ToUpper(value[0]) + value.Substring(1);
        }

        /// <summary>
        /// 获得复数
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderPlural(this string name)
        {
            Regex plural1 = new Regex("(?<keep>[^aeiou])y$");
            Regex plural2 = new Regex("(?<keep>[aeiou]y)$");
            Regex plural3 = new Regex("(?<keep>[sxzh])$");
            Regex plural4 = new Regex("(?<keep>[^sxzhy])$");

            if (plural1.IsMatch(name))
                return plural1.Replace(name, "${keep}ies");
            else if (plural2.IsMatch(name))
                return plural2.Replace(name, "${keep}s");
            else if (plural3.IsMatch(name))
                return plural3.Replace(name, "${keep}es");
            else if (plural4.IsMatch(name))
                return plural4.Replace(name, "${keep}s");

            return name;
        }

        /// <summary>
        /// 获得单数
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderSingle(this string name)
        {
            Regex plural1 = new Regex("(?<keep>[^aeiou])ies$");
            Regex plural2 = new Regex("(?<keep>[aeiou]y)s$");
            Regex plural3 = new Regex("(?<keep>[sxzh])es$");
            Regex plural4 = new Regex("(?<keep>[^sxzhyu])s$");

            if (plural1.IsMatch(name))
                return plural1.Replace(name, "${keep}y");
            else if (plural2.IsMatch(name))
                return plural2.Replace(name, "${keep}");
            else if (plural3.IsMatch(name))
                return plural3.Replace(name, "${keep}");
            else if (plural4.IsMatch(name))
                return plural4.Replace(name, "${keep}");

            return name;
        }

        /// <summary>
        /// Trim字符串,删除指定前后字符串
        /// </summary>
        /// <param name="source"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static string TrimString(this string source, string start, string end)
        {
            string ret = source;
            if (!string.IsNullOrEmpty(start))
            {
                if (source.IndexOf(start) == 0)
                    ret = source.Substring(start.Length);
            }
            if (!string.IsNullOrEmpty(end))
            {
                if (source.LastIndexOf(end) != -1 && source.LastIndexOf(end) == source.Length - end.Length)
                    ret = ret.Substring(0, ret.Length - end.Length);
            }
            return ret;
        }


        /// <summary>
        /// 实体类名称
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns></returns>
        public static string ToCoderEOClassName(this string name)
        {
            return name + "EO";
        }

        /// <summary>
        /// 逻辑类名称
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns></returns>
        public static string ToCoderMOClassName(this string name)
        {
            return name + "MO";
        }

        /// <summary>
        /// 转换成存储过程操作名称
        /// </summary>
        /// <param name="name">存储过程对象</param>
        /// <returns></returns>
        public static string ToCoderPOClassName(this string name)
        {
            return name + "PO";
        }

        /// <summary>
        /// 转换成枚举类型名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderEnumName(this string name)
        {
            return name + "Enum";
        }

        /// <summary>
        /// 获得映射的实体类的属性名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderPropertyName(this string name)
        {
            return name.ToCoderPascalCase();
        }

        /// <summary>
        /// 获得映射的实体类的字段名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderFieldName(this string name)
        {
            return "_" + name.ToCoderCamelCase();
        }

        /// <summary>
        /// 获得映射的实体类的参数名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderParameterName(this string name)
        {
            return name.ToCoderCamelCase();
        }

        /// <summary>
        /// 获取主键列映射的实体类的属性名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderPropertyNameByPrimaryColumn(this string name)
        {
            return "Original" + name.ToCoderPropertyName();
        }

        /// <summary>
        /// 获取主键列映射的实体类的字段名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderFieldNameByPrimaryColumn(this string name)
        {
            return "_original" + name.ToCoderPropertyName();
        }

        /// <summary>
        /// 获取外键列映射的实体类的属性名称
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ToCoderPropertyNameByForeignKey(this CoderTableKey key)
        {
            string result = string.Empty;

            foreach (CoderColumn column in key.ForeignColumns)
            {
                result += column.CodeName;
            }

            return result.ToCoderPropertyNameByForeignKey();
        }

        /// <summary>
        /// 获取外键列映射的实体类的属性名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderPropertyNameByForeignKey(this string name)
        {
            return name.ToCoderPropertyName() + "Source";
        }

        /// <summary>
        /// 获取外键列映射的实体类的字段名称
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ToCoderFieldNameByForeignKey(this CoderTableKey key)
        {
            return ToCoderPropertyNameByForeignKey(key).ToCoderFieldName();
        }

        /// <summary>
        /// 获取外键列映射的实体类的字段名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToCoderFieldNameByForeignKey(this string name)
        {
            return (name.ToCoderPropertyName() + "Source").ToCoderFieldName();
        }

        /// <summary>
        /// 通过换行符，将字符串拆成字符串数组
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <returns></returns>
        public static string[] ToCoderArrayByNewLine(this string source)
        {
            return source.Trim().Split(new string[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries);
        }
        /// <summary>
        /// 是否是合法的时间字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsDateTime(this string value)
        {
            DateTime dt;
            return DateTime.TryParse(value, out dt);
        }

        /// <summary>
        /// 是否是有效的guid
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsGuid(this string value)
        {
            Guid guid;
            return Guid.TryParse(value, out guid);
        }
        private static string _version;
        /// <summary>
        /// 获取主库的版本号
        /// </summary>
        /// <returns></returns>
        public static string GetAssemblyVersion()
        {
            if (string.IsNullOrEmpty(_version))
            {
                _version = Assembly.GetExecutingAssembly().GetName().Version.ToString(2);
            }
            return _version;
        }
        #endregion

        #region 扩展Coder
        /// <summary>
        /// 返回操作参数类型
        /// </summary>
        public enum IndexType
        {
            /// <summary>
            /// 参数描述
            /// </summary>
            ParamSummary,
            /// <summary>
            /// 方法名称 idAnd
            /// </summary>
            FunctionName,
            /// <summary>
            /// 方法参数列表 int id,
            /// </summary>
            ParamList,
            /// <summary>
            /// 方法中的调用方法参数 id, 
            /// </summary>
            InputParam,
            /// <summary>
            /// 方法中对象参数输入 item.Id, 
            /// </summary>
            AccessInput,
            /// <summary>
            /// 竖线分割格式化 {0}|{1}
            /// </summary>
            Format
        }

        private static readonly object _indexTypeActionsLock = new object();
        private static Dictionary<IndexType, Action<int, StringBuilder, int, CoderDataObject>> _indexTypeActions;

        private static Dictionary<IndexType, Action<int, StringBuilder, int, CoderDataObject>> GetIndexTypeActions()
        {
            if (_indexTypeActions == null)
            {
                lock (_indexTypeActionsLock)
                {
                    if (_indexTypeActions == null)
                    {
                        _indexTypeActions = new Dictionary<IndexType, Action<int, StringBuilder, int, CoderDataObject>>();

                        _indexTypeActions.Add(IndexType.ParamSummary,
                            (tabs, response, index, dataObject) =>
                            {
                                if (index != 0) response.AppendLine();
                                response.Append(GetCoderParamSummary(tabs, dataObject.CodeName.ToCoderParameterName(), dataObject.Description));
                            });

                        _indexTypeActions.Add(IndexType.FunctionName,
                           (tabs, response, index, dataObject) =>
                           {
                               if (index != 0) response.Append("And");
                               response.Append(dataObject.CodeName);
                           });

                        _indexTypeActions.Add(IndexType.ParamList,
                           (tabs, response, index, dataObject) =>
                           {
                               if (index != 0) response.Append(", ");
                               response.AppendFormat("{0} {1}", dataObject.CSharpType, dataObject.CodeName.ToCoderParameterName());
                           });


                        _indexTypeActions.Add(IndexType.InputParam,
                           (tabs, response, index, dataObject) =>
                           {
                               if (index != 0) response.Append(", ");
                               response.Append(dataObject.CodeName.ToCoderParameterName());
                           });

                        _indexTypeActions.Add(IndexType.AccessInput,
                           (tabs, response, index, dataObject) =>
                           {
                               if (index != 0) response.Append(", ");
                               response.AppendFormat("item.{0}", dataObject.CodeName);
                           });

                        _indexTypeActions.Add(IndexType.Format,
                         (tabs, response, index, dataObject) =>
                         {
                             if (index != 0) response.Append("|");
                             response.AppendFormat("{{{0}}}", index);
                         });
                    }
                }
            }
            return _indexTypeActions;
        }


        public static string GetDataObjectsInfo<T>(int tabs, IEnumerable<T> columns, IndexType type) where T : CoderDataObject
        {
            var response = new StringBuilder();
            var indexTypeFuns = GetIndexTypeActions();
            var indexTypeAction = indexTypeFuns[type];
            var index = 0;
            foreach (var dataObject in columns)
            {
                indexTypeAction(tabs, response, index++, dataObject);
            }
            return response.ToString();
        }
        #endregion

    }
}
